/**** Client code ****
 * Usage:
 * receives data from server and sorts data
 * then, server can send a query to client to check 
 * if the valid info is in this client.
 *
 * use qsort();
 * only use read & write to communicate with server
 */
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

// compare function for qsort()
int cmp(const void * , const void * );

// binary search function, return the position of target or -1;
int bin_search(int data[], int length, int target);

// reading from STDIN_FILENO and return result as an int;
int reading_data();

int main() { 
   //generate Debug file: file name is client_<pid>
   char a[10];
   sprintf(a, "%d", getpid());
   char fn[25] = "client_";
   strcat(fn, a);
   printf("%s\n", fn);
   FILE * f_debug = fopen(fn, "w");
   // number of items in this 
   int how_many;
   int * data_arr = NULL;
   //how_many = reading_data();
   read(STDIN_FILENO, &how_many, sizeof(int));

   //get how_many, if incorrect, exit()
   if(how_many <= 0) {
	   fclose(f_debug);
	   exit(1);
   }
   fprintf(f_debug, "total in this: %d\n", how_many);
   //allocate space for data array
   data_arr = (int *)calloc(how_many, sizeof(int));
   int read_in;
   int cnt = 0;
   int step = 1; //1: receiving data; 2: query, set by receiving -2; 

   while( (read_in = reading_data()) != -1) {
	   //get data from server
       if(read_in > 0 && step == 1) {
		   data_arr[cnt] = read_in;
		   cnt++;
       }
	   //start to query
	   else if(read_in == -2) {
          step = 2;
		  qsort(data_arr,cnt, sizeof(int), cmp);
		  int i;
		  for(i = 0; i< cnt; i++) {
               fprintf(f_debug, "%d\n", data_arr[i]);
		  }
		  fprintf(f_debug, "start to query\n");
       }
	   else if(read_in > 0 && step == 2) {
		   int has_item = bin_search(data_arr, how_many, read_in);
		   fprintf(f_debug, "receiving query number:%d, and pos is %d\n", read_in, has_item);
		   ssize_t wt_bytes = write(STDOUT_FILENO, &has_item, sizeof(int));
		   if(wt_bytes <= 0) {
			   fclose(f_debug);
			   free(data_arr);
			   exit(1);
		   }
	   }
	   else {
		  free(data_arr);
		  fclose(f_debug);
          exit(1);
	   }
   }
   fprintf(f_debug, "receiving exit signal -1.\n");
   free(data_arr);
   fclose(f_debug);
   return 0;
}


int cmp(const void * a, const void * b) {
    return *(int *)a - *(int *)b;
}


int bin_search(int data[], int length, int target) {
   int low = 0;
   int high = length - 1;

   while( low <= high ) {
       //avoid overflow
       int mid = ( low + high ) >> 1;
	   int mid_val = data[mid];

	   if( mid_val < target ) 
	       low = mid + 1;
	   else if ( mid_val > target )
		   high = high -1;
	   else 
		   return mid;
   }
   return -1;
}


int reading_data() {
    int read_in;
	ssize_t rd_bytes = read(STDIN_FILENO, &read_in, sizeof(int) );
    if(rd_bytes <= 0) {
		fprintf(stderr, "reading pipe error.\n");
		exit(1);
	}
    return read_in;
}













